{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "1dcefb88",
   "metadata": {
    "colab_type": "text",
    "id": "view-in-github"
   },
   "source": [
    "<a href=\"https://colab.research.google.com/github/wey-gu/jupyter_nebulagraph/blob/main/docs/get_started.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "favorite-value",
   "metadata": {
    "id": "favorite-value"
   },
   "source": [
    "This guide will help you walk through end to end process of tweaking NebulaGraph within Jupyter Notebook."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0d54dc6d-a87c-4290-8101-a058f04118d9",
   "metadata": {
    "jp-MarkdownHeadingCollapsed": true
   },
   "source": [
    "### Prerequirements"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "m7GeBbhBJXvM",
   "metadata": {
    "id": "m7GeBbhBJXvM"
   },
   "source": [
    "We need to have a running NebulaGraph Cluster. If you don't have one, you could leverage [NebulaGraph-Lite](https://github.com/wey-gu/nebulagraph-lite/) to do spawn an ad-hoc cluster, for more options please refer to [NebulaGraph Docs](https://docs.nebula-graph.io).\n",
    "\n",
    "> See also here for more NebulaGraph installation options: [NebulaGraph Installation Options](https://jupyter-nebulagraph.readthedocs.io/en/latest/installation/#nebulagraph-installation-options) from jupyter-nebulagraph documentation."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "DhZ5wSL7Jg9S",
   "metadata": {
    "id": "DhZ5wSL7Jg9S"
   },
   "outputs": [],
   "source": [
    "%pip install nebulagraph-lite"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "OdHPvUUMJ1k4",
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "OdHPvUUMJ1k4",
    "outputId": "4acc2d7c-6b85-4146-9e5b-23b5d7a4274f"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\u001b[1;30;43mStreaming output truncated to the last 5000 lines.\u001b[0m\n",
      "...var/lib/rpm/__db.002\n",
      "var/lib/rpm/__db.003\n",
      "2ccae830-d547-3d25-8d86-c8e24b20d62e\n",
      "Debug: using curl executable \n",
      "Debug: Localrepo homedir is /home/user/.udocker\n",
      "Debug: using curl executable \n",
      "Debug: already installed, installation skipped\n",
      "\u001b[1;3;38;2;102;81;145mSHOW TAGS: ResultSet(None)\u001b[0m\n",
      "Info: downloading layer sha256:73dde089847b2e7be0b3e12a438aa50dab9d29587a3f37512daf74271d6f7eb1\n",
      "Info: downloading layer sha256:8a5d5aed99ca3dd1343afcb47ea7136fa6350a36a31c12ebc62a6a92ddf1c7ef\n",
      "Info: downloading layer sha256:19bc7f3f0d802b7e8dc89786cfa0e18ab81bc501d90e1d24720d470e4e213c03\n",
      "Info: downloading layer sha256:7264a8db6415046d36d16ba98b79778e18accee6ffa71850405994cffa9be7de\n",
      "\u001b[1;3;38;2;160;81;149mInfo: loading basketballplayer dataset...\u001b[0m\n",
      "\u001b[1;3;38;2;212;80;135m\n",
      "  _   _      _           _        ____                 _     \n",
      " | \\ | | ___| |__  _   _| | __ _ / ___|_ __ __ _ _ __ | |__  \n",
      " |  \\| |/ _ | '_ \\| | | | |/ _` | |  _| '__/ _` | '_ \\| '_ \\ \n",
      " | |\\  |  __| |_) | |_| | | (_| | |_| | | | (_| | |_) | | | |\n",
      " |_| \\_|\\___|_.__/ \\__,_|_|\\__,_|\\____|_|  \\__,_| .__/|_| |_|\n",
      "                                                |_|          \n",
      "                                                lite version\n",
      "\u001b[0m\n",
      "\u001b[1;3;38;2;102;81;145m[ OK ] nebulagraph_lite started successfully!\u001b[0m\n",
      "CONTAINER ID                         P M NAMES              IMAGE               \n",
      "cac33b42-6851-316a-b32c-96641cb38492 . W ['nebula-metad']   vesoft/nebula-metad:v3\n",
      "2ccae830-d547-3d25-8d86-c8e24b20d62e . W ['nebula-storaged'] vesoft/nebula-storaged:v3\n",
      "2887f6d9-a872-3e17-b5cf-8ef4a7eb6e37 . W ['nebula-graphd']  vesoft/nebula-graphd:v3\n"
     ]
    }
   ],
   "source": [
    "from nebulagraph_lite import nebulagraph_let as ng_let\n",
    "\n",
    "n = ng_let()\n",
    "\n",
    "# This takes around 5 mins\n",
    "n.start()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "british-cream",
   "metadata": {
    "id": "british-cream"
   },
   "source": [
    "### Installation\n",
    "\n",
    "First, install with pip:\n",
    "\n",
    "```bash\n",
    "%pip install jupyter_nebulagraph\n",
    "```\n",
    "\n",
    "Second, load extension:\n",
    "\n",
    "```bash\n",
    "$load_ext ngql\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "70634402-5058-4577-8655-99ec7694eaed",
   "metadata": {},
   "outputs": [],
   "source": [
    "%pip install jupyter_nebulagraph"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "biological-summary",
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "biological-summary",
    "outputId": "6e92d22e-fb9d-4d05-eace-c2e729ad274d"
   },
   "outputs": [],
   "source": [
    "%load_ext ngql"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "embedded-olive",
   "metadata": {
    "id": "embedded-olive"
   },
   "source": [
    "### Connect to NebulaGraph\n",
    "\n",
    "With:\n",
    "\n",
    "```bash\n",
    "%ngql --address <ip> --port <port> --user <username> --password <password>\n",
    "```\n",
    "\n",
    "By default, spaces of the cluster will be printed."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "nasty-angel",
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 99
    },
    "id": "nasty-angel",
    "outputId": "e7781f17-cb40-4487-d305-fb6ab16d83de"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Connection Pool Created\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>Name</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>demo_basketballplayer</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>freebase_15k</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>nba</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>news</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                    Name\n",
       "0  demo_basketballplayer\n",
       "1           freebase_15k\n",
       "2                    nba\n",
       "3                   news"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "%ngql --address 127.0.0.1 --port 9669 --user root --password nebula"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8e97e917-7d57-4c44-8ae0-bfca59752032",
   "metadata": {},
   "source": [
    "## Query\n",
    "\n",
    "Then we could make a query after `Connection Pool Created` shown in the connection from last step:\n",
    "\n",
    "\n",
    "### Oneliner Query `%ngql`\n",
    "\n",
    "Option 1, it supports one line query as:\n",
    "```ngql\n",
    "%ngql <query_line>;\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "copyrighted-aberdeen",
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 112
    },
    "id": "copyrighted-aberdeen",
    "outputId": "dce6f075-417e-4fc6-fedd-d78f29aea19d"
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "\n",
       "  <div id=\"df-a4706433-fba3-40c7-ba29-848404392066\" class=\"colab-df-container\">\n",
       "    <div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>Name</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>Tony Parker</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>Manu Ginobili</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>\n",
       "    <div class=\"colab-df-buttons\">\n",
       "\n",
       "  <div class=\"colab-df-container\">\n",
       "    <button class=\"colab-df-convert\" onclick=\"convertToInteractive('df-a4706433-fba3-40c7-ba29-848404392066')\"\n",
       "            title=\"Convert this dataframe to an interactive table.\"\n",
       "            style=\"display:none;\">\n",
       "\n",
       "  <svg xmlns=\"http://www.w3.org/2000/svg\" height=\"24px\" viewBox=\"0 -960 960 960\">\n",
       "    <path d=\"M120-120v-720h720v720H120Zm60-500h600v-160H180v160Zm220 220h160v-160H400v160Zm0 220h160v-160H400v160ZM180-400h160v-160H180v160Zm440 0h160v-160H620v160ZM180-180h160v-160H180v160Zm440 0h160v-160H620v160Z\"/>\n",
       "  </svg>\n",
       "    </button>\n",
       "\n",
       "  <style>\n",
       "    .colab-df-container {\n",
       "      display:flex;\n",
       "      gap: 12px;\n",
       "    }\n",
       "\n",
       "    .colab-df-convert {\n",
       "      background-color: #E8F0FE;\n",
       "      border: none;\n",
       "      border-radius: 50%;\n",
       "      cursor: pointer;\n",
       "      display: none;\n",
       "      fill: #1967D2;\n",
       "      height: 32px;\n",
       "      padding: 0 0 0 0;\n",
       "      width: 32px;\n",
       "    }\n",
       "\n",
       "    .colab-df-convert:hover {\n",
       "      background-color: #E2EBFA;\n",
       "      box-shadow: 0px 1px 2px rgba(60, 64, 67, 0.3), 0px 1px 3px 1px rgba(60, 64, 67, 0.15);\n",
       "      fill: #174EA6;\n",
       "    }\n",
       "\n",
       "    .colab-df-buttons div {\n",
       "      margin-bottom: 4px;\n",
       "    }\n",
       "\n",
       "    [theme=dark] .colab-df-convert {\n",
       "      background-color: #3B4455;\n",
       "      fill: #D2E3FC;\n",
       "    }\n",
       "\n",
       "    [theme=dark] .colab-df-convert:hover {\n",
       "      background-color: #434B5C;\n",
       "      box-shadow: 0px 1px 3px 1px rgba(0, 0, 0, 0.15);\n",
       "      filter: drop-shadow(0px 1px 2px rgba(0, 0, 0, 0.3));\n",
       "      fill: #FFFFFF;\n",
       "    }\n",
       "  </style>\n",
       "\n",
       "    <script>\n",
       "      const buttonEl =\n",
       "        document.querySelector('#df-a4706433-fba3-40c7-ba29-848404392066 button.colab-df-convert');\n",
       "      buttonEl.style.display =\n",
       "        google.colab.kernel.accessAllowed ? 'block' : 'none';\n",
       "\n",
       "      async function convertToInteractive(key) {\n",
       "        const element = document.querySelector('#df-a4706433-fba3-40c7-ba29-848404392066');\n",
       "        const dataTable =\n",
       "          await google.colab.kernel.invokeFunction('convertToInteractive',\n",
       "                                                    [key], {});\n",
       "        if (!dataTable) return;\n",
       "\n",
       "        const docLinkHtml = 'Like what you see? Visit the ' +\n",
       "          '<a target=\"_blank\" href=https://colab.research.google.com/notebooks/data_table.ipynb>data table notebook</a>'\n",
       "          + ' to learn more about interactive tables.';\n",
       "        element.innerHTML = '';\n",
       "        dataTable['output_type'] = 'display_data';\n",
       "        await google.colab.output.renderOutput(dataTable, element);\n",
       "        const docLink = document.createElement('div');\n",
       "        docLink.innerHTML = docLinkHtml;\n",
       "        element.appendChild(docLink);\n",
       "      }\n",
       "    </script>\n",
       "  </div>\n",
       "\n",
       "\n",
       "<div id=\"df-c2f238be-9abc-4b6b-bb42-ab34b6011f2e\">\n",
       "  <button class=\"colab-df-quickchart\" onclick=\"quickchart('df-c2f238be-9abc-4b6b-bb42-ab34b6011f2e')\"\n",
       "            title=\"Suggest charts\"\n",
       "            style=\"display:none;\">\n",
       "\n",
       "<svg xmlns=\"http://www.w3.org/2000/svg\" height=\"24px\"viewBox=\"0 0 24 24\"\n",
       "     width=\"24px\">\n",
       "    <g>\n",
       "        <path d=\"M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zM9 17H7v-7h2v7zm4 0h-2V7h2v10zm4 0h-2v-4h2v4z\"/>\n",
       "    </g>\n",
       "</svg>\n",
       "  </button>\n",
       "\n",
       "<style>\n",
       "  .colab-df-quickchart {\n",
       "      --bg-color: #E8F0FE;\n",
       "      --fill-color: #1967D2;\n",
       "      --hover-bg-color: #E2EBFA;\n",
       "      --hover-fill-color: #174EA6;\n",
       "      --disabled-fill-color: #AAA;\n",
       "      --disabled-bg-color: #DDD;\n",
       "  }\n",
       "\n",
       "  [theme=dark] .colab-df-quickchart {\n",
       "      --bg-color: #3B4455;\n",
       "      --fill-color: #D2E3FC;\n",
       "      --hover-bg-color: #434B5C;\n",
       "      --hover-fill-color: #FFFFFF;\n",
       "      --disabled-bg-color: #3B4455;\n",
       "      --disabled-fill-color: #666;\n",
       "  }\n",
       "\n",
       "  .colab-df-quickchart {\n",
       "    background-color: var(--bg-color);\n",
       "    border: none;\n",
       "    border-radius: 50%;\n",
       "    cursor: pointer;\n",
       "    display: none;\n",
       "    fill: var(--fill-color);\n",
       "    height: 32px;\n",
       "    padding: 0;\n",
       "    width: 32px;\n",
       "  }\n",
       "\n",
       "  .colab-df-quickchart:hover {\n",
       "    background-color: var(--hover-bg-color);\n",
       "    box-shadow: 0 1px 2px rgba(60, 64, 67, 0.3), 0 1px 3px 1px rgba(60, 64, 67, 0.15);\n",
       "    fill: var(--button-hover-fill-color);\n",
       "  }\n",
       "\n",
       "  .colab-df-quickchart-complete:disabled,\n",
       "  .colab-df-quickchart-complete:disabled:hover {\n",
       "    background-color: var(--disabled-bg-color);\n",
       "    fill: var(--disabled-fill-color);\n",
       "    box-shadow: none;\n",
       "  }\n",
       "\n",
       "  .colab-df-spinner {\n",
       "    border: 2px solid var(--fill-color);\n",
       "    border-color: transparent;\n",
       "    border-bottom-color: var(--fill-color);\n",
       "    animation:\n",
       "      spin 1s steps(1) infinite;\n",
       "  }\n",
       "\n",
       "  @keyframes spin {\n",
       "    0% {\n",
       "      border-color: transparent;\n",
       "      border-bottom-color: var(--fill-color);\n",
       "      border-left-color: var(--fill-color);\n",
       "    }\n",
       "    20% {\n",
       "      border-color: transparent;\n",
       "      border-left-color: var(--fill-color);\n",
       "      border-top-color: var(--fill-color);\n",
       "    }\n",
       "    30% {\n",
       "      border-color: transparent;\n",
       "      border-left-color: var(--fill-color);\n",
       "      border-top-color: var(--fill-color);\n",
       "      border-right-color: var(--fill-color);\n",
       "    }\n",
       "    40% {\n",
       "      border-color: transparent;\n",
       "      border-right-color: var(--fill-color);\n",
       "      border-top-color: var(--fill-color);\n",
       "    }\n",
       "    60% {\n",
       "      border-color: transparent;\n",
       "      border-right-color: var(--fill-color);\n",
       "    }\n",
       "    80% {\n",
       "      border-color: transparent;\n",
       "      border-right-color: var(--fill-color);\n",
       "      border-bottom-color: var(--fill-color);\n",
       "    }\n",
       "    90% {\n",
       "      border-color: transparent;\n",
       "      border-bottom-color: var(--fill-color);\n",
       "    }\n",
       "  }\n",
       "</style>\n",
       "\n",
       "  <script>\n",
       "    async function quickchart(key) {\n",
       "      const quickchartButtonEl =\n",
       "        document.querySelector('#' + key + ' button');\n",
       "      quickchartButtonEl.disabled = true;  // To prevent multiple clicks.\n",
       "      quickchartButtonEl.classList.add('colab-df-spinner');\n",
       "      try {\n",
       "        const charts = await google.colab.kernel.invokeFunction(\n",
       "            'suggestCharts', [key], {});\n",
       "      } catch (error) {\n",
       "        console.error('Error during call to suggestCharts:', error);\n",
       "      }\n",
       "      quickchartButtonEl.classList.remove('colab-df-spinner');\n",
       "      quickchartButtonEl.classList.add('colab-df-quickchart-complete');\n",
       "    }\n",
       "    (() => {\n",
       "      let quickchartButtonEl =\n",
       "        document.querySelector('#df-c2f238be-9abc-4b6b-bb42-ab34b6011f2e button');\n",
       "      quickchartButtonEl.style.display =\n",
       "        google.colab.kernel.accessAllowed ? 'block' : 'none';\n",
       "    })();\n",
       "  </script>\n",
       "</div>\n",
       "\n",
       "    </div>\n",
       "  </div>\n"
      ],
      "text/plain": [
       "            Name\n",
       "0    Tony Parker\n",
       "1  Manu Ginobili"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "%ngql USE basketballplayer;\n",
    "%ngql MATCH (v:player{name:\"Tim Duncan\"})-->(v2:player) RETURN v2.player.name AS Name;"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "necessary-performance",
   "metadata": {
    "id": "necessary-performance"
   },
   "source": [
    "### Multiline Query `%%ngql`\n",
    "\n",
    "Option 2, to perform multiple queries in one go.\n",
    "\n",
    "```ngql\n",
    "%%ngql\n",
    "<line 0>;\n",
    "<line 1>;\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "northern-anatomy",
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 143
    },
    "id": "northern-anatomy",
    "outputId": "6b757289-223d-4e51-d4f3-b18718265872"
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>Type</th>\n",
       "      <th>Name</th>\n",
       "      <th>Count</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>Tag</td>\n",
       "      <td>player</td>\n",
       "      <td>54</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>Tag</td>\n",
       "      <td>team</td>\n",
       "      <td>30</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>Edge</td>\n",
       "      <td>follow</td>\n",
       "      <td>82</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>Edge</td>\n",
       "      <td>serve</td>\n",
       "      <td>146</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>Space</td>\n",
       "      <td>vertices</td>\n",
       "      <td>84</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>Space</td>\n",
       "      <td>edges</td>\n",
       "      <td>228</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "    Type      Name  Count\n",
       "0    Tag    player     54\n",
       "1    Tag      team     30\n",
       "2   Edge    follow     82\n",
       "3   Edge     serve    146\n",
       "4  Space  vertices     84\n",
       "5  Space     edges    228"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "%%ngql\n",
    "USE basketballplayer;\n",
    "SUBMIT JOB STATS;\n",
    "SHOW STATS;"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7235d052-f095-4c1c-80c8-b0aba7b693b8",
   "metadata": {},
   "source": [
    "### Cheatsheet"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "apart-questionnaire",
   "metadata": {
    "id": "apart-questionnaire"
   },
   "source": [
    "The only takeout should be:\n",
    "\n",
    "You could always get help from `%ngql help` for some details of supported magics && examples you could copy from.\n",
    "\n",
    "```ngql\n",
    "%ngql help\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "oriental-vault",
   "metadata": {
    "id": "oriental-vault"
   },
   "source": [
    "### Using Variables in Query String\n",
    "\n",
    "We used Jinja2(https://jinja.palletsprojects.com/) as templating method for variables in query string:\n",
    "\n",
    "```python\n",
    "trainer = \"Sue\"\n",
    "```\n",
    "\n",
    "```ngql\n",
    "%%ngql\n",
    "GO FROM \"{{ trainer }}\" OVER owns_pokemon YIELD owns_pokemon._dst as pokemon_id | GO FROM $-.pokemon_id OVER owns_pokemon REVERSELY YIELD owns_pokemon._dst AS Trainer_Name;\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "disciplinary-sustainability",
   "metadata": {
    "id": "disciplinary-sustainability"
   },
   "outputs": [],
   "source": [
    "vid = \"player100\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "bizarre-absorption",
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 143
    },
    "id": "bizarre-absorption",
    "outputId": "bfe52aaa-e049-490f-f068-c0cfa73d4d9d"
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>FriendOf</th>\n",
       "      <th>Team</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>Boris Diaw</td>\n",
       "      <td>Spurs</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>Boris Diaw</td>\n",
       "      <td>Jazz</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>Boris Diaw</td>\n",
       "      <td>Suns</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "     FriendOf   Team\n",
       "0  Boris Diaw  Spurs\n",
       "1  Boris Diaw   Jazz\n",
       "2  Boris Diaw   Suns"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "%%ngql\n",
    "MATCH (v)<-[e:follow]- (v2)-[e2:serve]->(v3)\n",
    "  WHERE id(v) == \"{{ vid }}\"\n",
    "RETURN v2.player.name AS FriendOf, v3.team.name AS Team LIMIT 3;"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e7ac3264-b8f4-407d-977c-221af74c5d0f",
   "metadata": {},
   "source": [
    "## Result Handling\n",
    "\n",
    "By default, the query result is a Pandas Dataframe, and we could access that by read from variable `_`.\n",
    "\n",
    "### Dataframe Result(default)\n",
    "\n",
    "For instance:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "23a4d66a-db0e-4e31-a93e-eb4a6198b7b8",
   "metadata": {},
   "outputs": [],
   "source": [
    "df = _"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "deda4471-f260-42ec-9abb-7f8d3994f139",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>FriendOf</th>\n",
       "      <th>Team</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>Boris Diaw</td>\n",
       "      <td>Spurs</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>Boris Diaw</td>\n",
       "      <td>Jazz</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>Boris Diaw</td>\n",
       "      <td>Suns</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "     FriendOf   Team\n",
       "0  Boris Diaw  Spurs\n",
       "1  Boris Diaw   Jazz\n",
       "2  Boris Diaw   Suns"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "motivated-pantyhose",
   "metadata": {
    "id": "motivated-pantyhose"
   },
   "source": [
    "### Tweaking Raw Result(Optional)\n",
    "\n",
    "By default the result `ngql_result_style` is `pandas`, this enabled us to have a table view rendered by Jupyter Notebook.\n",
    "\n",
    "While, if you would like to get raw results from `neutron3-python` itself, just configure it as below on the fly:\n",
    "\n",
    "```\n",
    "%config IPythonNGQL.ngql_result_style=\"raw\"\n",
    "```\n",
    "\n",
    "And after querying, the result will be stored in `_`, plesae then refer it to a new variable for further ad-hoc tweaking on it like:\n",
    "```\n",
    "$ngql <query>;\n",
    "\n",
    "result = _\n",
    "\n",
    "dir(result)\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "designed-civilian",
   "metadata": {
    "id": "designed-civilian"
   },
   "outputs": [],
   "source": [
    "%config IPythonNGQL.ngql_result_style=\"raw\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "quiet-armor",
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "quiet-armor",
    "outputId": "be9dd4fd-ae87-40fd-f402-3f9df53798bf"
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "ResultSet(keys: ['dst(EDGE)'], values: [\"player100\"],[\"player102\"],[\"player125\"],[\"player101\"],[\"player125\"])"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "%%ngql\n",
    "USE demo_basketballplayer;\n",
    "GO 2 STEPS FROM \"player102\" OVER follow YIELD dst(edge);"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "rising-strip",
   "metadata": {
    "id": "rising-strip"
   },
   "outputs": [],
   "source": [
    "r = _"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "attractive-steel",
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 35
    },
    "id": "attractive-steel",
    "outputId": "7e863ba2-18f1-4a3c-bce8-407993fb757c"
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'player100'"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "r.column_values(\"dst(EDGE)\")[0].cast()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "located-freeze",
   "metadata": {
    "id": "located-freeze"
   },
   "source": [
    "Now we change back to `pandas` `ngql_result_style`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "characteristic-preliminary",
   "metadata": {
    "id": "characteristic-preliminary"
   },
   "outputs": [],
   "source": [
    "%config IPythonNGQL.ngql_result_style=\"pandas\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "commercial-orchestra",
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 143
    },
    "id": "commercial-orchestra",
    "outputId": "c84ef119-7c66-4bfa-add6-1ee77756817b"
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>team_name</th>\n",
       "      <th>start_year</th>\n",
       "      <th>player_name</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>Spurs</td>\n",
       "      <td>1997</td>\n",
       "      <td>Tim Duncan</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>Trail Blazers</td>\n",
       "      <td>2006</td>\n",
       "      <td>LaMarcus Aldridge</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>Spurs</td>\n",
       "      <td>2015</td>\n",
       "      <td>LaMarcus Aldridge</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "       team_name  start_year        player_name\n",
       "0          Spurs        1997         Tim Duncan\n",
       "1  Trail Blazers        2006  LaMarcus Aldridge\n",
       "2          Spurs        2015  LaMarcus Aldridge"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "%%ngql\n",
    "GO FROM \"player100\", \"player102\" OVER serve\n",
    "  WHERE properties(edge).start_year > 1995\n",
    "YIELD DISTINCT properties($$).name AS team_name, properties(edge).start_year AS start_year, properties($^).name AS player_name;"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5b91e20d-98f0-4470-abef-72a9b376c96c",
   "metadata": {},
   "source": [
    "## Load Data from CSV\n",
    "\n",
    "Since 0.9.0, it is supported to load data into NebulaGraph with ease.\n",
    "\n",
    "We could load data from a local path or a URL:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "a4748070-8bb7-449a-b81d-900bb9368425",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Parsed 3 vertices 'demo_basketballplayer' for tag 'player' in memory\n"
     ]
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "f690001c9b7c4475a1633b8bcfc2865e",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Loading Vertices:   0%|          | 0/1 [00:00<?, ?it/s]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Loaded 3 of 3 vertices\n",
      "Successfully loaded 3 vertices 'demo_basketballplayer' for tag 'player'\n"
     ]
    }
   ],
   "source": [
    "%ng_load --source https://github.com/wey-gu/ipython-ngql/raw/main/examples/actor.csv --tag player --vid 0 --props 1:name,2:age --space basketballplayer"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "550727c0-1aea-4e1e-96c5-9334a04e7f9b",
   "metadata": {},
   "source": [
    "### `%ng_load` docs\n",
    "\n",
    "The %ng_load magic command is designed to facilitate the loading of data from CSV files into NebulaGraph as vertices or edges. This command streamlines the process of importing data directly within a Jupyter Notebook environment, making it easier for users to work with NebulaGraph databases.\n",
    "\n",
    "\n",
    "#### Usage\n",
    "\n",
    "```\n",
    "%ng_load --source <source> [--header] --space <space> [--tag <tag>] [--vid <vid>] [--edge <edge>] [--src <src>] [--dst <dst>] [--rank <rank>] [--props <props>] [-b <batch>]\n",
    "```\n",
    "\n",
    "#### Arguments\n",
    "\n",
    "- `--header`: (Optional) Indicates if the CSV file contains a header row. If this flag is set, the first row of the CSV will be treated as column headers.\n",
    "- `-n`, `--space` (Required): Specifies the name of the NebulaGraph space where the data will be loaded.\n",
    "- `-s`, `--source` (Required): The file path or URL to the CSV file. Supports both local paths and remote URLs.\n",
    "- `-t`, `--tag`: The tag name for vertices. Required if loading vertex data.\n",
    "- `--vid`: The column index for the vertex ID. Required if loading vertex data.\n",
    "- `-e`, `--edge`: The edge type name. Required if loading edge data.\n",
    "- `--src`: The column index for the source vertex ID when loading edges.\n",
    "- `--dst`: The column index for the destination vertex ID when loading edges.\n",
    "- `--rank`: (Optional) The column index for the rank value of edges. Default is None.\n",
    "- `--props`: (Optional) Comma-separated column indexes for mapping to properties. The format for mapping is column_index:property_name.\n",
    "- `-b`, `--batch` (Optional): Batch size for data loading. Default is 256.\n",
    "\n",
    "#### Examples\n",
    "\n",
    "Loading Vertices\n",
    "\n",
    "To load vertex data from a local CSV file named actor.csv into the basketballplayer space with the player tag, where the vertex ID is in the first column, and the properties name and age are in the second and third columns, respectively:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "c2e4195b-3b3f-46a2-a154-7642afb5ac45",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Parsed 3 vertices 'demo_basketballplayer' for tag 'player' in memory\n"
     ]
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "dc3a99261e7b41d492b7ac055a898b2a",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Loading Vertices:   0%|          | 0/1 [00:00<?, ?it/s]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Loaded 3 of 3 vertices\n",
      "Successfully loaded 3 vertices 'demo_basketballplayer' for tag 'player'\n"
     ]
    }
   ],
   "source": [
    "%ng_load --source actor.csv --tag player --vid 0 --props 1:name,2:age --space basketballplayer"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e75c73f6-ae5f-487d-b31e-7f810d9038e1",
   "metadata": {},
   "source": [
    "Loading Edges\n",
    "\n",
    "To load edge data from a local CSV file named follow_with_rank.csv into the basketballplayer space with the follow edge type, where the source vertex ID is in the first column, the destination vertex ID is in the second column, the property degree is in the third column, and the rank is in the fourth column:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "id": "c96c0500-03ec-452b-97e5-4f3c7e18b9f5",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Parsed 1 edges 'demo_basketballplayer' for edge type 'follow' in memory\n"
     ]
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "466a765af70f4696bfcf08104ab184dc",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Loading Edges:   0%|          | 0/1 [00:00<?, ?it/s]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Loaded 1 of 1 edges\n",
      "Successfully loaded 1 edges 'demo_basketballplayer' for edge type 'follow'\n"
     ]
    }
   ],
   "source": [
    "%ng_load --source follow_with_rank.csv --edge follow --src 0 --dst 1 --props 2:degree --rank 3 --space basketballplayer"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0f04c49d",
   "metadata": {
    "id": "0f04c49d"
   },
   "source": [
    "## Draw nGQL queries `%ng_draw`\n",
    "\n",
    "We could render Graphs with `%ng_draw` thanks to the upstream project `pyvis`.\n",
    "\n",
    "<img width=\"948\" alt=\"ng_draw_demo\" src=\"https://github.com/wey-gu/jupyter_nebulagraph/assets/1651790/02454358-8ec7-42a3-815b-e58298184514\">\n",
    "\n",
    "<img width=\"1142\" alt=\"ng_draw_demo_1\" src=\"https://github.com/wey-gu/jupyter_nebulagraph/assets/1651790/c17d7491-922a-4930-a49c-c55f4e2adee4\">\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9b573f5a",
   "metadata": {},
   "source": [
    "Or `%ng_draw <one_line_query>`, `%%ng_draw <multiline_query>` instead of drawing the result of the last query.\n",
    "\n",
    "\n",
    "<img width=\"1142\" alt=\"ng_draw_demo_1\" src=\"https://github.com/wey-gu/jupyter_nebulagraph/assets/1651790/a6e3b2d4-0320-4287-bd2f-537cff77c1de\">\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c911efa2",
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "c911efa2",
    "outputId": "a99b212d-ab22-4be5-d432-3e6e526dc40a"
   },
   "outputs": [],
   "source": [
    "%pip install pyvis"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "id": "423e852e",
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 206
    },
    "id": "423e852e",
    "outputId": "db1cf97c-ab27-4ad4-9d40-4f10b75dbf16"
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>p</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>(\"player148\" :player{age: 45, name: \"Jason Kid...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>(\"player148\" :player{age: 45, name: \"Jason Kid...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>(\"player148\" :player{age: 45, name: \"Jason Kid...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>(\"player148\" :player{age: 45, name: \"Jason Kid...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>(\"player148\" :player{age: 45, name: \"Jason Kid...</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                                                   p\n",
       "0  (\"player148\" :player{age: 45, name: \"Jason Kid...\n",
       "1  (\"player148\" :player{age: 45, name: \"Jason Kid...\n",
       "2  (\"player148\" :player{age: 45, name: \"Jason Kid...\n",
       "3  (\"player148\" :player{age: 45, name: \"Jason Kid...\n",
       "4  (\"player148\" :player{age: 45, name: \"Jason Kid..."
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "%ngql match p=(:player)-[]->() return p LIMIT 5"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "69171089",
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 551
    },
    "id": "69171089",
    "outputId": "806ee4da-49ab-4cab-ee69-7551486c1788"
   },
   "outputs": [],
   "source": [
    "##uncomment to draw\n",
    "# %ng_draw"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "id": "84ac453e",
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 143
    },
    "id": "84ac453e",
    "outputId": "0d377247-5e1f-473a-84e0-6e077e461bae"
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>nodes</th>\n",
       "      <th>relationships</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>[(\"player101\" :player{})]</td>\n",
       "      <td>[(\"player101\")-[:serve@0{}]-&gt;(\"team204\"), (\"pl...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>[(\"player102\" :player{}), (\"player100\" :player...</td>\n",
       "      <td>[(\"player102\")-[:serve@0{}]-&gt;(\"team203\"), (\"pl...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>[(\"player144\" :player{}), (\"player112\" :player...</td>\n",
       "      <td>[(\"player144\")-[:serve@0{}]-&gt;(\"team214\"), (\"pl...</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                                               nodes  \\\n",
       "0                          [(\"player101\" :player{})]   \n",
       "1  [(\"player102\" :player{}), (\"player100\" :player...   \n",
       "2  [(\"player144\" :player{}), (\"player112\" :player...   \n",
       "\n",
       "                                       relationships  \n",
       "0  [(\"player101\")-[:serve@0{}]->(\"team204\"), (\"pl...  \n",
       "1  [(\"player102\")-[:serve@0{}]->(\"team203\"), (\"pl...  \n",
       "2  [(\"player144\")-[:serve@0{}]->(\"team214\"), (\"pl...  "
      ]
     },
     "execution_count": 23,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "%ngql GET SUBGRAPH 2 STEPS FROM \"player101\" YIELD VERTICES AS nodes, EDGES AS relationships;"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "id": "8d406b2d",
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 551
    },
    "id": "8d406b2d",
    "outputId": "5bec7726-46b1-4c1e-94af-6603ca7370b9"
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "\n",
       "        <iframe\n",
       "            width=\"100%\"\n",
       "            height=\"500px\"\n",
       "            src=\"../assets/nebulagraph.html\"\n",
       "            frameborder=\"0\"\n",
       "            allowfullscreen\n",
       "            \n",
       "        ></iframe>\n",
       "        "
      ],
      "text/plain": [
       "<IPython.lib.display.IFrame at 0x7f81095a7f20>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": [
       "<class 'pyvis.network.Network'> |N|=36 |E|=84"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "%ng_draw"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8f59b93d-1776-4a97-b318-20f74dd26458",
   "metadata": {
    "id": "8f59b93d-1776-4a97-b318-20f74dd26458"
   },
   "source": [
    "## Draw Graph Schema `%ng_draw_schema`\n",
    "\n",
    "Also, we could quickly draw the schema with `%ng_draw_schema`, which samples all types of edges to show us what the graph looks like.\n",
    "\n",
    "This example comes from a dataset/space called demo_supplychain, to get those datasets named `demo_*`, you could install NebulaGraph Studio and click Download to have them ingested into NebulaGraph in one minute.\n",
    "\n",
    "<img width=\"1008\" alt=\"ng_draw_schema_demo\" src=\"https://github.com/wey-gu/ipython-ngql/assets/1651790/e851289f-0009-42e8-984e-416417f2af8b\">\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "id": "c8ab3493-37a5-42ea-80aa-30b9d88ffae8",
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 53
    },
    "id": "c8ab3493-37a5-42ea-80aa-30b9d88ffae8",
    "outputId": "fab51f77-1560-4b4a-9bcf-a0cfd242c20b"
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "Empty DataFrame\n",
       "Columns: []\n",
       "Index: []"
      ]
     },
     "execution_count": 25,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "%ngql CREATE SPACE demo_supplychain(partition_num=1, replica_factor=1, vid_type=fixed_string(128));"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "4db6378d-f093-4e33-8fc4-99006a144ab9",
   "metadata": {},
   "outputs": [],
   "source": [
    "!sleep 10\n",
    "%ngql USE demo_supplychain"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "9e718475-e0d3-4cea-bb96-3c245d8304fe",
   "metadata": {},
   "outputs": [],
   "source": [
    "%%ngql\n",
    "\n",
    "CREATE TAG IF NOT EXISTS car_model(name string, number string, year int, type string, engine_type string, size string, seats int);\n",
    "CREATE TAG IF NOT EXISTS feature(name string, number string, type string, state string);\n",
    "CREATE TAG IF NOT EXISTS `part`(name string, number string, price double, `date` string);\n",
    "CREATE TAG IF NOT EXISTS supplier(name string, address string, contact string, phone_number string);\n",
    "CREATE EDGE IF NOT EXISTS with_feature(version string);\n",
    "CREATE EDGE IF NOT EXISTS is_composed_of(version string);\n",
    "CREATE EDGE IF NOT EXISTS is_supplied_by(version string);"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "364e0e8d-0b67-460f-b78a-ebd2bb5d8f71",
   "metadata": {},
   "outputs": [],
   "source": [
    "!sleep 10"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b68961c6-08bf-4d01-8185-2a5f96e7069e",
   "metadata": {},
   "outputs": [],
   "source": [
    "%%ngql\n",
    "\n",
    "INSERT VERTEX `car_model`(`name`, `number`, `year`, `type`, `engine_type`, `size`, `seats`) VALUES \"m_1\":(\"Model A\", \"001\", 2023, \"Sedan\", \"Gasoline\", \"Compact\", 4), \"m_2\":(\"Model B\", \"002\", 2023, \"Coupe\", \"Electric\", \"Compact\", 2), \"m_3\":(\"Model C\", \"003\", 2022, \"SUV\", \"Hybrid\", \"Large\", 7), \"m_4\":(\"Model D\", \"004\", 2022, \"Truck\", \"Diesel\", \"Extra Large\", 5), \"m_5\":(\"Model E\", \"005\", 2021, \"Sedan\", \"Electric\", \"Medium\", 5), \"m_6\":(\"Model F\", \"006\", 2021, \"Convertible\", \"Gasoline\", \"Compact\", 2), \"m_7\":(\"Model G\", \"007\", 2023, \"Crossover\", \"Hybrid\", \"Medium\", 5), \"m_8\":(\"Model H\", \"008\", 2020, \"Hatchback\", \"Electric\", \"Compact\", 4), \"m_9\":(\"Model I\", \"009\", 2022, \"Sedan\", \"Gasoline\", \"Large\", 5), \"m_10\":(\"Model J\", \"010\", 2021, \"SUV\", \"Hybrid\", \"Extra Large\", 7);\n",
    "INSERT VERTEX `supplier`(`name`, `address`, `contact`, `phone_number`) VALUES \"s_31\":(\"Supplier A\", \"123 Street\", \"John Doe\", \"1234567890\"), \"s_32\":(\"Supplier B\", \"456 Avenue\", \"Emily Smith\", \"0987654321\"), \"s_33\":(\"Supplier C\", \"789 Boulevard\", \"Robert Brown\", \"1112233445\"), \"s_34\":(\"Supplier D\", \"101 Place\", \"Maria Johnson\", \"2223344556\"), \"s_35\":(\"Supplier E\", \"202 Drive\", \"Michael Williams\", \"3334455667\"), \"s_36\":(\"Supplier F\", \"303 Lane\", \"Susan Miller\", \"4445566778\"), \"s_37\":(\"Supplier G\", \"404 Road\", \"Chris Lee\", \"5556677889\"), \"s_38\":(\"Supplier H\", \"505 Street\", \"Jane Wilson\", \"6667788990\"), \"s_39\":(\"Supplier I\", \"606 Way\", \"Brian Anderson\", \"7778899001\"), \"s_40\":(\"Supplier J\", \"707 Avenue\", \"Linda Hall\", \"8889900112\");\n",
    "INSERT VERTEX `feature`(`name`, `number`, `type`, `state`) VALUES \"f_11\":(\"Sunroof\", \"F001\", \"Optional\", \"Available\"), \"f_12\":(\"Bluetooth\", \"F002\", \"Standard\", \"Available\"), \"f_13\":(\"Navigation\", \"F003\", \"Optional\", \"N/A\"), \"f_14\":(\"Heated Seats\", \"F004\", \"Standard\", \"Available\"), \"f_15\":(\"Backup Camera\", \"F005\", \"Optional\", \"Available\"), \"f_16\":(\"Leather Seats\", \"F006\", \"Standard\", \"Available\"), \"f_17\":(\"Adaptive Cruise\", \"F007\", \"Optional\", \"Available\"), \"f_18\":(\"Blind Spot Monitor\", \"F008\", \"Standard\", \"Available\"), \"f_19\":(\"Remote Start\", \"F009\", \"Optional\", \"N/A\"), \"f_20\":(\"Apple CarPlay\", \"F010\", \"Standard\", \"Available\");\n",
    "INSERT VERTEX `part`(`name`, `number`, `price`, `date`) VALUES \"p_21\":(\"Brake Pad\", \"P001\", 50, \"2023-01-01\"), \"p_22\":(\"Engine\", \"P002\", 2000, \"2023-05-03\"), \"p_23\":(\"Tire\", \"P003\", 100, \"2022-08-14\"), \"p_24\":(\"Transmission\", \"P004\", 1500, \"2022-02-20\"), \"p_25\":(\"Radiator\", \"P005\", 250, \"2022-06-15\"), \"p_26\":(\"Window Glass\", \"P006\", 60, \"2021-11-23\"), \"p_27\":(\"Battery\", \"P007\", 120, \"2023-03-09\"), \"p_28\":(\"Headlight\", \"P008\", 90, \"2023-07-30\"), \"p_29\":(\"Alternator\", \"P009\", 180, \"2022-09-04\"), \"p_30\":(\"Air Filter\", \"P010\", 20, \"2023-04-22\");\n",
    "INSERT EDGE `with_feature`(`version`) VALUES \"m_1\"->\"f_12\":(\"1.0\"), \"m_2\"->\"f_13\":(\"1.0\"), \"m_3\"->\"f_14\":(\"1.1\"), \"m_4\"->\"f_15\":(\"1.2\"), \"m_5\"->\"f_11\":(\"1.0\"), \"m_6\"->\"f_12\":(\"1.0\"), \"m_7\"->\"f_13\":(\"1.0\"), \"m_8\"->\"f_14\":(\"1.0\"), \"m_9\"->\"f_15\":(\"1.0\"), \"m_10\"->\"f_11\":(\"1.0\"), \"m_2\"->\"f_12\":(\"1.0\"), \"m_3\"->\"f_13\":(\"1.1\"), \"m_4\"->\"f_14\":(\"1.2\"), \"m_5\"->\"f_15\":(\"1.0\"), \"m_6\"->\"f_11\":(\"1.0\"), \"m_7\"->\"f_12\":(\"1.0\"), \"m_8\"->\"f_13\":(\"1.0\"), \"m_9\"->\"f_14\":(\"1.0\"), \"m_10\"->\"f_15\":(\"1.0\"), \"m_1\"->\"f_11\":(\"1.0\"), \"m_2\"->\"f_12\":(\"1.2\"), \"m_3\"->\"f_13\":(\"1.1\"), \"m_4\"->\"f_12\":(\"1.0\"), \"m_5\"->\"f_15\":(\"1.3\"), \"m_6\"->\"f_11\":(\"1.2\"), \"m_7\"->\"f_14\":(\"1.0\"), \"m_8\"->\"f_13\":(\"1.1\"), \"m_9\"->\"f_15\":(\"1.2\"), \"m_10\"->\"f_12\":(\"1.1\"), \"m_1\"->\"f_13\":(\"1.3\"), \"m_2\"->\"f_14\":(\"1.0\"), \"m_3\"->\"f_11\":(\"1.1\"), \"m_4\"->\"f_14\":(\"1.0\"), \"m_5\"->\"f_15\":(\"1.2\"), \"m_6\"->\"f_13\":(\"1.0\"), \"m_7\"->\"f_12\":(\"1.1\"), \"m_8\"->\"f_15\":(\"1.1\"), \"m_9\"->\"f_11\":(\"1.2\"), \"m_10\"->\"f_14\":(\"1.3\"), \"m_2\"->\"f_11\":(\"1.0\"), \"m_3\"->\"f_12\":(\"1.1\"), \"m_5\"->\"f_14\":(\"1.0\"), \"m_6\"->\"f_15\":(\"1.1\"), \"m_8\"->\"f_12\":(\"1.2\"), \"m_9\"->\"f_13\":(\"1.0\"), \"m_1\"->\"f_15\":(\"1.2\"), \"m_7\"->\"f_13\":(\"1.3\"), \"m_4\"->\"f_11\":(\"1.0\"), \"m_10\"->\"f_15\":(\"1.1\");\n",
    "INSERT EDGE `is_composed_of`(`version`) VALUES \"f_11\"->\"p_21\":(\"1.0\"), \"f_12\"->\"p_22\":(\"1.0\"), \"f_13\"->\"p_23\":(\"1.1\"), \"f_14\"->\"p_24\":(\"1.2\"), \"f_15\"->\"p_21\":(\"1.0\"), \"f_16\"->\"p_22\":(\"1.0\"), \"f_17\"->\"p_23\":(\"1.0\"), \"f_18\"->\"p_24\":(\"1.0\"), \"f_19\"->\"p_25\":(\"1.0\"), \"f_20\"->\"p_26\":(\"1.0\"), \"f_11\"->\"p_27\":(\"1.0\"), \"f_12\"->\"p_28\":(\"1.0\"), \"f_13\"->\"p_29\":(\"1.1\"), \"f_14\"->\"p_30\":(\"1.2\"), \"f_15\"->\"p_21\":(\"1.0\"), \"f_16\"->\"p_22\":(\"1.0\"), \"f_17\"->\"p_23\":(\"1.0\"), \"f_18\"->\"p_24\":(\"1.0\"), \"f_19\"->\"p_25\":(\"1.0\"), \"f_20\"->\"p_26\":(\"1.0\");\n",
    "INSERT EDGE `is_supplied_by`(`version`) VALUES \"p_21\"->\"s_31\":(\"1.0\"), \"p_22\"->\"s_32\":(\"1.0\"), \"p_23\"->\"s_33\":(\"1.1\"), \"p_24\"->\"s_34\":(\"1.2\"), \"p_25\"->\"s_35\":(\"1.0\"), \"p_26\"->\"s_36\":(\"1.0\"), \"p_27\"->\"s_37\":(\"1.0\"), \"p_28\"->\"s_38\":(\"1.0\"), \"p_29\"->\"s_39\":(\"1.1\"), \"p_30\"->\"s_40\":(\"1.2\"), \"p_21\"->\"s_31\":(\"1.0\"), \"p_22\"->\"s_32\":(\"1.0\"), \"p_23\"->\"s_33\":(\"1.1\"), \"p_24\"->\"s_34\":(\"1.2\"), \"p_25\"->\"s_35\":(\"1.0\"), \"p_26\"->\"s_36\":(\"1.0\"), \"p_27\"->\"s_37\":(\"1.0\"), \"p_28\"->\"s_38\":(\"1.0\"), \"p_29\"->\"s_39\":(\"1.1\"), \"p_30\"->\"s_40\":(\"1.2\");"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "id": "1c71735c-a039-43af-b3c8-414323a21d75",
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 551
    },
    "id": "1c71735c-a039-43af-b3c8-414323a21d75",
    "outputId": "a75c602c-a55e-4446-9a4e-3881433f9f5a"
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "\n",
       "        <iframe\n",
       "            width=\"100%\"\n",
       "            height=\"500px\"\n",
       "            src=\"../assets/nebulagraph_schema.html\"\n",
       "            frameborder=\"0\"\n",
       "            allowfullscreen\n",
       "            \n",
       "        ></iframe>\n",
       "        "
      ],
      "text/plain": [
       "<IPython.lib.display.IFrame at 0x7f8108b71e80>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": [
       "<class 'pyvis.network.Network'> |N|=4 |E|=3"
      ]
     },
     "execution_count": 26,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "%ng_draw_schema"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "forbidden-carter",
   "metadata": {
    "id": "forbidden-carter"
   },
   "source": [
    "## `% ngql help`!\n",
    "\n",
    "Again, all you have to remember is to use `$ngql help` to have all hints :-)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "id": "5a67dfdf",
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "5a67dfdf",
    "outputId": "276bacba-c855-42ee-8248-0a990a828db4"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "        Supported Configurations:\n",
      "        ------------------------\n",
      "        \n",
      "        > How to config ngql_result_style in \"raw\", \"pandas\"\n",
      "        %config IPythonNGQL.ngql_result_style=\"raw\"\n",
      "        %config IPythonNGQL.ngql_result_style=\"pandas\"\n",
      "\n",
      "        > How to config ngql_verbose in True, False\n",
      "        %config IPythonNGQL.ngql_verbose=True\n",
      "\n",
      "        > How to config max_connection_pool_size\n",
      "        %config IPythonNGQL.max_connection_pool_size=10\n",
      "\n",
      "        Quick Start:\n",
      "        -----------\n",
      "\n",
      "        > Connect to Neubla Graph\n",
      "        %ngql --address 127.0.0.1 --port 9669 --user user --password password\n",
      "\n",
      "        > Use Space\n",
      "        %ngql USE basketballplayer\n",
      "\n",
      "        > Query\n",
      "        %ngql SHOW TAGS;\n",
      "\n",
      "        > Multile Queries\n",
      "        %%ngql\n",
      "        SHOW TAGS;\n",
      "        SHOW HOSTS;\n",
      "\n",
      "        Reload ngql Magic\n",
      "        %reload_ext ngql\n",
      "\n",
      "        > Variables in query, we are using Jinja2 here\n",
      "        name = \"nba\"\n",
      "        %ngql USE \"{{ name }}\"\n",
      "\n",
      "        > Query and draw the graph\n",
      "\n",
      "        %ngql GET SUBGRAPH 2 STEPS FROM \"player101\" YIELD VERTICES AS nodes, EDGES AS relationships;\n",
      "\n",
      "        %ng_draw\n",
      "\n",
      "        > Query and draw the graph schema\n",
      "\n",
      "        %ng_draw_schema\n",
      "\n",
      "        > Load data from CSV file into NebulaGraph as vertices or edges\n",
      "        %ng_load --source actor.csv --tag player --vid 0 --props 1:name,2:age --space basketballplayer\n",
      "\n",
      "        #actor.csv\n",
      "        \"player999\",\"Tom Hanks\",30\n",
      "        \"player1000\",\"Tom Cruise\",40\n",
      "\n",
      "        %ng_load --source follow_with_rank.csv --edge follow --src 0 --dst 1 --props 2:degree --rank 3 --space basketballplayer\n",
      "\n",
      "        #follow_with_rank.csv\n",
      "        \"player999\",\"player1000\",50,1\n",
      "\n",
      "        %ng_load --source follow.csv --edge follow --src 0 --dst 1 --props 2:degree --space basketballplayer\n",
      "\n",
      "        #follow.csv\n",
      "        \"player999\",\"player1000\",50\n",
      "\n",
      "        %ng_load --source https://github.com/wey-gu/ipython-ngql/raw/main/examples/actor.csv --tag player --vid 0 --props 1:name,2:age --space demo_basketballplayer -b 2\n",
      "\n",
      "\n",
      "        \n"
     ]
    }
   ],
   "source": [
    "%ngql help"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "69f72765-480c-4c7d-b5b4-9ccd26dbffb1",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "colab": {
   "include_colab_link": true,
   "provenance": []
  },
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
